
#include <BRender>
#include <BMaterial>
#include <BSphere>
#include "member_BSphere.h"

using namespace BWE;

#define member					(*(member_BSphere*)_ptr)
#define member_allocate()		_ptr = new member_BSphere(this)
#define member_release()		delete (member_BSphere*)_ptr

BSphere::BSphere()
{
	member_allocate();
}
BSphere::BSphere(BReal radius)
{
	member_allocate();
	this->setRadius(radius);
}
BSphere::BSphere(BReal radius, int sides, int segments)
{
	member_allocate();
	this->setRadius(radius);
	this->setSides(sides);
	this->setSegments(segments);
}
BSphere::~BSphere()
{
	member_release();
}

void BSphere::copy(const BShape* other)
{
	BShape::copy(other);
	if (const BSphere* sphere = dynamic_cast<const BSphere*>(other))
	{
		member.radius = sphere_member(other)->radius;
		member.sides = sphere_member(other)->sides;
		member.segments = sphere_member(other)->segments;
		member.coses = sphere_member(other)->coses;
		member.sines = sphere_member(other)->sines;
	}
}
BShape* BSphere::clone() const
{
	BSphere* sphere = new BSphere();
	sphere->copy(this);
	return sphere;
}

void BSphere::setRadius(BReal radius)
{
	if (member.radius != radius)
	{
		member.radius = radius;
		this->dirty();
	}
}
BReal BSphere::radius() const
{
	return member.radius;
}

void BSphere::setSides(int sides)
{
	if (member.sides != sides)
	{
		member.sides = sides;
		member.prepare();
		this->dirty();
	}
}
int BSphere::sides() const
{
	return member.sides;
}

void BSphere::setSegments(int segments)
{
	if (member.segments != segments)
	{
		member.segments = segments;
		this->dirty();
	}
}
int BSphere::segments() const
{
	return member.segments;
}

BVector BSphere::vertex(const BVector& direct) const
{
	return direct * member.radius;
}
BVector BSphere::inertia(BReal mass) const
{
	BReal elem = BReal(0.4) * mass * member.radius * member.radius;
	return BVector(elem, elem, elem);
}

void BSphere::refresh(BBox& box)
{
	BSpace space;
	space.min() = BVector(-member.radius, -member.radius, -member.radius);
	space.max() = BVector(member.radius, member.radius, member.radius);
	member.rebuild();
	box = space;
}
void BSphere::render(BRender& render)
{
	BGeometry::render(render);
}
